package com.satis.compose.get.widget

import android.graphics.Bitmap
import android.graphics.Canvas
import android.view.HardwareCanvasManager
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.layout.boundsInRoot
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.viewinterop.AndroidView

/**
 * @author sunshaobei on 2022/9/9
 * Compose 对包裹控件截图
 */

data class CaptureState(
    val capture: Boolean = false
)

fun MutableState<CaptureState>.capture() {
    this.value = this.value.copy(capture = true)
}

private fun MutableState<CaptureState>.captureComplete() {
    this.value = this.value.copy(capture = false)
}

@Composable
fun rememberCaptureController(): MutableState<CaptureState> {
    return remember {
        mutableStateOf(CaptureState(capture = false))
    }
}

@Composable
fun ComposeCapture(
    captureController: MutableState<CaptureState> = rememberCaptureController(),
    onSaveBitmap: (Bitmap?) -> Unit,
    content: @Composable () -> Unit
) {
    var bounds = remember {
        mutableStateOf<Rect?>(null)
    }
    if (captureController.value.capture) {
        CaptureView(captureController = captureController, onSaveBitmap = onSaveBitmap,bounds = bounds,content = content)
    } else {
        Surface(modifier = Modifier.onGloballyPositioned {
            bounds.value = it.boundsInRoot()
        },content = content)

    }
}

@Composable
private fun CaptureView(
    captureController: MutableState<CaptureState>,
    bounds: MutableState<Rect?>,
    onSaveBitmap: ((Bitmap?) -> Unit)? = null,
    content: @Composable () -> Unit
) {
    AndroidView(factory = {
        FrameLayout(it).apply {
            layoutParams = ViewGroup.LayoutParams(
                (bounds.value!!.right - bounds.value!!.left).toInt(),
                (bounds.value!!.bottom - bounds.value!!.top).toInt()
            )
            val composeView = ComposeView(it).apply {
                setContent {
                    content()
                }
            }
            drawListener(composeView,this,captureController,onSaveBitmap)
            addView(
                composeView, ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
            )

        }
    })
}

private fun drawListener(
    composeView: View, viewGroup: ViewGroup,
    captureController: MutableState<CaptureState>,
    onSaveBitmap: ((Bitmap?) -> Unit)? = null,
) {
    val drawListener = object : ViewTreeObserver.OnDrawListener {
        var remove = false
        override fun onDraw() {
            if (composeView.width > 0) {
                if (!remove) {
                    remove = true
                    composeView.post {
                        val bitmap = getViewGroupBitmap(viewGroup)
                        captureController.captureComplete()
                        onSaveBitmap?.invoke(bitmap)
                        composeView.viewTreeObserver.removeOnDrawListener(this)
                    }
                }

            }
        }
    }
    composeView.viewTreeObserver.addOnDrawListener(drawListener)
}

/**
 * @param viewGroup viewGroup
 * @return Bitmap
 */
private fun getViewGroupBitmap(viewGroup: ViewGroup): Bitmap? {
    val hardwareCanvasManager = HardwareCanvasManager()
    val canvas = hardwareCanvasManager.createCanvas(viewGroup.width, viewGroup.height)
//    val canvas = Canvas(bitmap)
    viewGroup.draw(canvas)
    val buildBitmap = hardwareCanvasManager.buildBitmap()
    hardwareCanvasManager.clean()
    return buildBitmap
}
